package andev.aandroidlib.util;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.ThumbnailUtils;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Locale;

/**
 *
 */
public class FileOperator {
    public static final int FILES_NULL_PTR = -1;
    public static final int SUCCESS = 1;
    public static final int FAILED = 0;
    private Handler originalHandler = null;
    private int runNum = 0;
    private Object syncKey = new Object();
    private long showTimeMillis = 0;
    private String[][] MIME_MapTable = {
            //{后缀名，MIME类型}
            {".m3u", "audio/x-mpegurl"},
            {".m4a", "audio/mp4a-latm"},
            {".m4b", "audio/mp4a-latm"},
            {".m4p", "audio/mp4a-latm"},
            {".mp2", "audio/x-mpeg"},
            {".mp3", "audio/x-mpeg"},
            {".mpga", "audio/mpeg"},
            {".wav", "audio/x-wav"},
            {".wma", "audio/x-ms-wma"},
            {".wmv", "audio/x-ms-wmv"},
            {".rmvb", "audio/x-pn-realaudio"},
            {".ogg", "audio/ogg"},
            {".3gp", "video/3gpp"},
            {".asf", "video/x-ms-asf"},
            {".avi", "video/x-msvideo"},
            {".m4u", "video/vnd.mpegurl"},
            {".m4v", "video/x-m4v"},
            {".mov", "video/quicktime"},
            {".mp4", "video/mp4"},
            {".mpe", "video/mpeg"},
            {".mpeg", "video/mpeg"},
            {".mpg", "video/mpeg"},
            {".mpg4", "video/mp4"},
            {".bmp", "image/bmp"},
            {".gif", "image/gif"},
            {".jpeg", "image/jpeg"},
            {".jpg", "image/jpeg"},
            {".png", "image/png"},
            {".txt", "text/plain"},
            {".c", "text/plain"},
            {".conf", "text/plain"},
            {".cpp", "text/plain"},
            {".java", "text/plain"},
            {".h", "text/plain"},
            {".log", "text/plain"},
            {".rc", "text/plain"},
            {".prop", "text/plain"},
            {".sh", "text/plain"},
            {".xml", "text/plain"},
            {".htm", "text/html"},
            {".html", "text/html"},
            {".apk", "application/vnd.android.package-archive"},
            {".bin", "application/octet-stream"},
            {".class", "application/octet-stream"},
            {".doc", "application/msword"},
            {".docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document"},
            {".xls", "application/vnd.ms-excel"},
            {".xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"},
            {".exe", "application/octet-stream"},
            {".gtar", "application/x-gtar"},
            {".gz", "application/x-gzip"},
            {".z", "application/x-compress"},
            {".7z", "application/x-7z-compressed"},
            {".zip", "application/x-zip-compressed"},
            {".tgz", "application/x-compressed"},
            {".tar", "application/x-tar"},
            {".jar", "application/java-archive"},
            {".js", "application/x-javascript"},
            {".msg", "application/vnd.ms-outlook"},
            {".mpc", "application/vnd.mpohun.certificate"},
            {".pdf", "application/pdf"},
            {".pps", "application/vnd.ms-powerpoint"},
            {".ppt", "application/vnd.ms-powerpoint"},
            {".pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation"},
            {".rtf", "application/rtf"},
            {".wps", "application/vnd.ms-works"},
            {"", "*/*"}
    };
    private int deleteNums = 0;

    /**
     * Angus 获取图片缩略图
     *
     * @param imagePath
     * @param width
     * @param height
     * @return
     */
    public static Bitmap getImageThumbnail(String imagePath, int width, int height) {
        Bitmap bitmap = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(imagePath), width, height, ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
        return bitmap;
    }

    /**
     * Angus 获取视频缩略图
     *
     * @param videoPath
     * @param width
     * @param height
     * @return
     */
    public static Bitmap getVideoThumbnail(String videoPath, int width, int height) {
        Bitmap bitmap = ThumbnailUtils.extractThumbnail(ThumbnailUtils.createVideoThumbnail(videoPath, MediaStore.Video.Thumbnails.MINI_KIND), width, height, ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
        return bitmap;
    }

    /**
     * Angus 2015/8/2 获得文件中的文本内容，这个方法应该只被适用于文本类文件
     *
     * @param file
     * @return String
     */
    public String getFileText(File file) {
        if (file == null) {
            return null;
        }
        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            return getStreamText(fileInputStream);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public String getStreamText(InputStream inputStream) {
        StringBuffer content = new StringBuffer();
        try {
            InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                content.append(line);
                content.append('\n');
            }
            inputStreamReader.close();
            bufferedReader.close();
            inputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return content.toString();
    }

    /**
     * Angus 爬取目录下的所有子文件/文件夹
     *
     * @param context
     * @param dir
     * @param crawlListener
     */
    public void crawlDir(final Context context, File dir, final CrawlListener crawlListener) {
        if (!dir.exists()) {
            return;
        }

        final File[] files = dir.listFiles();
        if (files == null) {
            return;
        }

        if (originalHandler == null)
            originalHandler = new Handler(context.getMainLooper()) {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    if (msg.what == crawlListener.ON_CRAWL) {
                        crawlListener.onCrawlHandleUI((String) msg.obj);
                    } else if (msg.what == crawlListener.ON_CRAWL_END)
                        crawlListener.onCrawlEnd();
                }
            };

        new Thread() {
            @Override
            public void run() {
                synchronized (syncKey) {
                    runNum++;
                }
                for (File file : files) {
                    String absolutePath = file.getAbsolutePath();
                    if (crawlListener.onCrawlHandleData(absolutePath)) {
                        synchronized (syncKey) {
                            if (System.currentTimeMillis() - showTimeMillis > 1000) {
                                Message message = new Message();
                                message.what = crawlListener.ON_CRAWL;
                                message.obj = absolutePath;
                                originalHandler.sendMessage(message);
                                showTimeMillis = System.currentTimeMillis();
                            }
                        }
                    }

                    crawlDir(context, file, crawlListener);
                }
                synchronized (syncKey) {
                    runNum--;
                    if (runNum == 0) {
                        syncKey.notifyAll();
                        try {
                            syncKey.wait(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        if (runNum == 0)
                            originalHandler.sendEmptyMessage(crawlListener.ON_CRAWL_END);
                    }
                }
            }
        }.start();

    }

    /**
     * Angus 爬取多个目录下的所有子文件/文件夹
     *
     * @param context
     * @param dirs
     * @param crawlListener
     */
    public void crawlDirs(final Context context, final File[] dirs, final CrawlListener crawlListener) {
        if (originalHandler == null)
            originalHandler = new Handler(context.getMainLooper()) {
                @Override
                public void handleMessage(Message msg) {
                    super.handleMessage(msg);
                    if (msg.what == crawlListener.ON_CRAWL) {
                        crawlListener.onCrawlHandleUI((String) msg.obj);
                    } else if (msg.what == crawlListener.ON_CRAWL_END)
                        crawlListener.onCrawlEnd();
                }
            };

        new Thread() {
            @Override
            public void run() {
                synchronized (syncKey) {
                    runNum++;
                }

                for (File dir : dirs) {
                    if (!dir.exists()) continue;

                    String absolutePath = dir.getAbsolutePath();
                    if (crawlListener.onCrawlHandleData(absolutePath)) {
                        synchronized (syncKey) {
                            if (System.currentTimeMillis() - showTimeMillis > 1000) {
                                Message message = new Message();
                                message.what = crawlListener.ON_CRAWL;
                                message.obj = absolutePath;
                                originalHandler.sendMessage(message);
                                showTimeMillis = System.currentTimeMillis();
                            }
                        }
                    }

                    final File[] files = dir.listFiles();
                    if (files == null) continue;
                    crawlDirs(context, files, crawlListener);
                }
                synchronized (syncKey) {
                    runNum--;
                    if (runNum == 0) {
                        syncKey.notifyAll();
                        try {
                            syncKey.wait(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        if (runNum == 0)
                            originalHandler.sendEmptyMessage(crawlListener.ON_CRAWL_END);
                        else syncKey.notifyAll();
                    }
                }
            }
        }.start();
    }

    /**
     * Angus 2015/8/2 tell system to open a file
     *
     * @param context a context to use startActivity(intent) function
     * @param file
     * @param MIME    the file MIME,can be null to automatically detect the file's MIME type
     */
    public void openFile(Context context, File file, String MIME) {
        Intent intent = new Intent();
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setAction(Intent.ACTION_VIEW);
        if (MIME == null)
            intent.setDataAndType(Uri.fromFile(file), getFileMIME(file));
        else
            intent.setDataAndType(Uri.fromFile(file), MIME);
        context.startActivity(intent);
    }

    /**
     * Angus get the file MIME type
     *
     * @param file
     * @return String
     */
    public String getFileMIME(File file) {
        String fileName = file.getName();
        String extension = "";
        String MIME = "*/*";

        int dotIndex = fileName.lastIndexOf(".");
        if (dotIndex < 0) {
            return MIME;
        }
        extension = fileName.substring(dotIndex).toLowerCase(Locale.ENGLISH);
        int length = MIME_MapTable.length;
        for (int i = 0; i < length; i++) {
            if (extension.equals(MIME_MapTable[i][0])) {
                MIME = MIME_MapTable[i][1];
                break;
            }
        }
        return MIME;
    }

    /**
     * Angus get the extension of the file
     *
     * @param file
     * @return
     */
    public String getFileExtension(File file) {
        String fileName = file.getName();
        if (file.isDirectory()) {
            return "文件夹";
        }
        int dotIndex = fileName.lastIndexOf(".");
        if (dotIndex < 0) {
            return "";
        } else {
            return fileName.substring(dotIndex);
        }
    }

    public int getDirChildCount(File file) {
        if (file.isFile()) return 1;
        File[] files = file.listFiles();
        if (files != null)
            return file.listFiles().length;
        else
            return 0;
    }

    /**
     * Angus 获取文件(夹)的大小
     *
     * @param file
     * @return
     */
    public long getFileSize(File file) {
        long size = 0;
        size += file.length();
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            for (int i = 0; i < files.length; i++) {
                size += getFileSize(files[i]);
            }
        }
        return size;
    }

    /**
     * 2015年7月23日下午6:34:16
     * Angus 删除文件(夹)
     * getFilesDir(),getCacheDir(),getExternalCacheDir(),getExternalFilesDir(type),Environment.getExternalStorageDirectory().....等等
     *
     * @param file 文件对象
     * @return FILES_NULL_PTR文件不存在，FAILED删除失败，>=SUCCESS为删除的文件(夹)个数，即>=1个
     */
    public int deleteFile(File file) {
        if (file.isFile()) return file.delete() ? SUCCESS : FAILED;

        File[] files = file.listFiles();
        if (files == null) return FILES_NULL_PTR;

        for (File e : files) {
            if (deleteFile(e) == SUCCESS)
                deleteNums++;
        }
        return file.delete() ? ++deleteNums : FAILED;
    }

    public interface CrawlListener {
        int ON_CRAWL = 1;
        int ON_CRAWL_END = 0;

        boolean onCrawlHandleData(String absolutePath);

        void onCrawlHandleUI(String absolutePath);

        void onCrawlEnd();
    }


}
